<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <button>点击</button>
  <script>
    // 自定义事件 

    // 把事件函数 统一管理起来 

    // 事件监听可以监听多个对象
    // document.querySelector("button").addEventListener("click",function(){
    //     console.log("fn");
    // })
    // document.querySelector("button").addEventListener("click",function(){
    //     console.log("fn");
    // })

    let eventObj = {}; // 可以保存多个事件名 和多个事件函数 

    /* 
    {
      // 一个事件存储 对应多个函数
      click: [fn1, fn2, fn3],
      mouseover: [fn1, fn2, fn3],
      myevent: []
    }
    */

    // 观察者模式 当对象间存在一对多关系时，则使用观察者模式 当一个对象的状态发生改变时，所有依赖于它的对象都得到通知并被自动更新

    // 添加事件 通过一个全局的对象 保存了事件名及事件函数
    function addEvent (eventName, fn) {
      // 把多个事件名称 和多个事件函数 保存起来
      // 第一次绑定的时候 把 事件名初始化成一个数组
      // 判断eventObj里有没有事件 如果没有 让事件变成空数组
      if (typeof eventObj[eventName] === "undefined") {
        eventObj[eventName] = [];
      }
      // 保存事件 
      eventObj[eventName].push(fn);
    }
    addEvent("myevent", function () {
      console.log(11)
    })
    addEvent("myevent", function () {
      console.log(222)
    })
    addEvent("myevent2", function () {
      console.log(11)
    })
    addEvent("myevent2", function () {
      console.log(222)
    })
    console.log(eventObj);



    // 手写一个触发函数
    function trigger (eventName) {
      // 把之前保存的函数 取出来执行就可以了
      if (typeof eventObj[eventName] !== "undefined") {
        eventObj[eventName].forEach(fn => {
          fn();
        })
      } else {
        throw Error("参数传递错误");
      }
    }

    

    setTimeout(() => {
      trigger("myevent");
      trigger('myevent2')
    }, 2000);



    /*
    // 改造成类 
    // 和自定义事件有关的内容 都在这个类里；
    class MyEvent {
      constructor() {
        // 事件对象
        this.eventObj = {};
      }
      addEvent (eventName, fn) {
        // 把多个事件名称 和多个事件函数 保存起来
        // 第一次绑定的时候 把 事件名初始化成一个数组
        if (typeof this.eventObj[eventName] === "undefined") {
          this.eventObj[eventName] = [];
        }
        // 保存事件 
        this.eventObj[eventName].push(fn);
      }
      trigger (eventName) {
        // 把之前保存的函数 取出来执行就可以了
        if (typeof this.eventObj[eventName] !== "undefined") {
          this.eventObj[eventName].forEach(fn => {
            fn();
          })
        } else {
          throw Error("参数传递错误");
        }
      }
    }
    let myevent = new MyEvent();
    myevent.addEvent("myevent", function () {
      console.log(1111);
    })
    myevent.addEvent("myevent", function () {
      console.log(2222);
    })
    setTimeout(() => {
      myevent.trigger("myevent");
    }, 2000); 
    */

  </script>
</body>

</html>